home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
ov143b.zip
/
OVFILE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-04
|
26KB
|
779 lines
/* 068 9-Jun-87 ovfile.c
Copyright (c) 1987 by Blue Sky Software. All rights reserved.
*/
#include <stdio.h>
#include <dos.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "ov.h"
#include "overr.h"
#include "direct.h"
#include "dosfile.h"
#include "strmem.h"
static int stowidx;
static FILE_ENT *stowfp;
static DRIVE_ENT *drvlst = NULL;
static char *notitself = "You can't copy a file to itself!";
static char *mustbedir = "Enter a drive and/or directory name!";
extern WINDOW cw;
extern int diridx;
extern char **dirlst;
extern FILE_ENT files[];
extern char *cantopen, *none_tagged;
DRIVE_ENT *findrive(int);
struct search_block *nxtfile();
char far *largest_f(unsigned int, unsigned int *);
unsigned int readbuf(int,char far *,unsigned int);
unsigned int writebuf(int,char far *,unsigned int);
char *strupr(), *strchr(), *dirplus(FILE_ENT *, char *);
char *parsepath(char *, char *, char *, int, char **, char **);
int free_f(char far *), stowfile(struct search_block *, char *);
int add2windows(char *, char *, FILE_ENT *), delfromwins(char *, char *);
/******************************************************************************
** G E T F I L E S **
*****************************************************************************/
getfiles() { /* get data for the files in the current dir */
int firsttime;
char pathbuf[MAX_PATHLEN+6];
register struct search_block *sbp;
cw.files_size = 0; /* no files yet */
firsttime = TRUE; /* tell nxtfile() its the first call */
stowidx = 0; /* start storing at the begining */
stowfp = files;
/* if showall mode is active, call scantree to get all files, otherwise
scan the current dir ourselves */
if (cw.showall) { /* scan the current disk? */
*pathbuf = '\0';
strncat(pathbuf,cw.dirbuf,2);
scantree("\\",pathbuf,0x16,stowfile); /* scan entire disk */
} else /* scan the current directory */
while (stowidx < MAX_FILES && (sbp = nxtfile("*.*",0x16,&firsttime)))
stowfile(sbp,NULL);
/* sort the file names if there are any, also set nfiles */
if (cw.nfiles = stowidx)
sort_files(NULL);
/* set current file pointer to the first file */
cw.curidx = 0;
/* set file counters */
cw.num_files = cw.nfiles; /* files in the dir */
cw.num_tagged = 0; /* no files tagged yet */
cw.tag_size = 0;
}
/*****************************************************************************
S T O W F I L E
*****************************************************************************/
static int
stowfile(sbp,dirp) /* store a file in files[] */
register struct search_block *sbp;
char *dirp;
{
register int len;
static char *lastdir = NULL;
register FILE_ENT *fp = stowfp; /* fast stow pointer */
/* if dirp is not NULL, this call is defining which dir is being scanned,
add this dir name to the showall dir list - return NZ (keep going) if
dir name added okay, 0 (stop scanning) if can't add dir name - don't
incr diridx unless everything is okay. The dir name passed will always
have a trailing \ which we don't really want - don't keep it unless
this happens to be the root dir (len == 3) */
if (dirp) {
if (diridx < MAX_DIR) {
len = strlen(dirp);
dirlst[diridx++] = lastdir = Strndup(dirp,len > 3 ? len-1 : len);
return(1);
}
return(0);
}
/* ignore . and .. entries. If the file mask is defined, make
sure the file name matches. Make sure the file attributes
match the selection attributes */
if (stowidx >= MAX_FILES || *sbp->fn == '.' ||
(cw.selatrs & sbp->attrib) != sbp->attrib ||
(*cw.mask && (cw.maskcmp != match_name(sbp->fn,cw.mask))))
return(1); /* don't want this one, but keep looking */
/* we want the file, fill in files[] entry */
fp->size = sbp->size;
fp->flags = sbp->attrib & 0x3f;
fp->index = stowidx++;
fp->date = sbp->date;
fp->time = sbp->time;
strcpy(fp->name,sbp->fn);
fp->dirp = cw.showall ? lastdir : cw.dirbuf; /* point to files dir str */
cw.files_size += fp->size; /* accumulate total size */
stowfp++; /* update for next time */
return(1); /* keep looking */
}
/******************************************************************************
** I N F O **
*****************************************************************************/
info() { /* toggle the extended info display */
cw.info_display ^= 1; /* toggle info on/off */
infocnt(cw.info_display ? 1 : -1); /* one more or less info window */
adjust_window(); /* resize the window data */
update_window(1); /* display files in new format */
}
/******************************************************************************
** C O P Y _ C U R R E N T **
*****************************************************************************/
copy_current() { /* copy the current file */
FILE_ENT tmpfent;
register FILE_ENT *fp;
register DRIVE_ENT *dp;
char *dest, *target, *todir, *tofn;
dest = prompt("Copy current file","Copy to where? ",NULL,0,MAX_REPLY);
if (strlen(dest) == 0)
return;
fp = &files[cw.curidx];
target = parsepath(fp->dirp,fp->name,dest,isadir(fp->dirp,dest),&todir,&tofn);
if (strcmp(fp->dirp,todir) != 0 || strcmp(fp->name,tofn) != 0) {
if (copyfile(fp,target)) {
tmpfent = *fp; /* new file will have */
tmpfent.flags |= ARCHIVE; /* ARCHIVE attrib on */
add2windows(todir,tofn,&tmpfent);
dp = findrive(*todir);
getvolsiz(dp->drive,&dp->vol_size,&dp->vol_free,&dp->clustersiz);
}
} else /* attempt to copy file to itself! */
show_error(0,0,1,notitself);
free(target);
free(todir);
free(tofn);
}
/******************************************************************************
** C O P Y _ T A G G E D **
*****************************************************************************/
copy_tagged() { /* mass copy of tagged files to somewhere */
int i, ch;
FILE_ENT tmpfent;
register FILE_ENT *fp;
register DRIVE_ENT *dp;
char *dir, *target, *todir, *tofn;
if (cw.num_tagged == 0) /* are there any tagged files? */
show_error(0,NONE_TAGGED,1,none_tagged);
dir = prompt("Copy tagged files","Copy to which dir? ",NULL,0,MAX_REPLY);
if (strlen(dir) == 0)
return;
if (!isadir(cw.dirbuf,dir)) /* user must give a directory name */
show_error(0,MUST_BE_DIR,1,mustbedir);
/* Okay, copy the tagged files */
for (fp = files, i = 0; i < cw.nfiles && !brkout(); i++, fp++)
if (fp->flags & TAGGED) {
disp_msg(2,"Copying ",fp->name);
target = parsepath(fp->dirp,fp->name,dir,1,&todir,&tofn);
if (strcmp(fp->dirp,todir) != 0 || strcmp(fp->name,tofn) != 0) {
if (copyfile(fp,target)) {
tmpfent = *fp; /* new file will have */
tmpfent.flags |= ARCHIVE; /* ARCHIVE attrib on */
add2windows(todir,tofn,&tmpfent);
}
} else /* trying to copy a file to itself */
show_error(0,0,1,notitself);
free(target); /* release temp strings */
free(todir);
free(tofn);
}
clr_msg(); /* clear last copying msg */
/* update volume stats after copy */
dp = strlen(dir) > 1 && dir[1] == ':' ? findrive(*dir) : cw.drivep;
getvolsiz(dp->drive,&dp->vol_size,&dp->vol_free,&dp->clustersiz);
}
/******************************************************************************
** C O P Y F I L E **
*****************************************************************************/
static int
copyfile(fp,to) /* copy from to */
register FILE_ENT *fp;
char *to;
{
char *fn;
char far *buffer;
int fd, td, rc = 0;
unsigned int bufsiz, len;
static char *copyabort = " -- copy aborted";
/* allocate space for the in memory copy buffer */
buffer = largest_f(63*1024,&bufsiz); /* get largest possible blk up 2 63k */
if (bufsiz < 1024) { /* give it up if < 1k available */
if (bufsiz) /* release the tiny buffer */
free_f(buffer);
show_error(0,0,2,"No free memory to allocate copy buffer",copyabort);
goto error1;
}
/* open the from file */
fd = open(fn = fname(fp),O_RDONLY|O_BINARY);
free(fn);
if (fd == -1) {
show_error(SHOW_DOS,0,3,cantopen,fp->name,": ");
goto error2;
}
/* open the output file */
if ((td = open(to,O_CREAT|O_BINARY|O_TRUNC|O_RDWR,S_IWRITE)) == -1) {
show_error(SHOW_DOS,0,3,cantopen,to,": ");
goto error3;
}
/* copy the file, a buffer at a time */
while (len = readbuf(fd,buffer,bufsiz))
if (writebuf(td,buffer,len) < len) {
show_error(0,0,3,"Error writting to ",to,": Disk may be full");
goto error4;
}
setftime(td,fp->date,fp->time); /* to file time = from file */
rc = 1; /* the copy seems to have worked */
error4: close(td); /* close the to file */
if (!rc) /* erase to file if there was an */
unlink(to); /* error while trying to copy */
error3: close(fd); /* close the from file */
error2: free_f(buffer); /* release copy buffer */
/* set new file attrib's = old file + ACRHIVE */
if (rc)
setattrib(to,(fp->flags & (ARCHIVE|SYSTEM|HIDDEN|RDONLY)) | ARCHIVE);
error1: return(rc); /* tell caller if we worked */
}
/******************************************************************************
** E R A S E _ C U R R E N T **
*****************************************************************************/
erase_current() { /* erase the current file */
int ch;
char askmsg[30];
register FILE_ENT *fp;
fp = &files[cw.curidx];
strcpy(askmsg,"Erase ");
strcat(askmsg,fp->name);
strcat(askmsg," ? (y/N): ");
ch = ask(askmsg);
if (yes(ch))
if (delfile(fp)) { /* delete the file */
delfromwins(fp->dirp,fp->name); /* remove from windows */
getvolsiz(*cw.dirbuf,&cw.drivep->vol_size, /* vol stats have changed */
&cw.drivep->vol_free,&cw.drivep->clustersiz);
}
}
/*****************************************************************************
E R A S E _ T A G G E D
*****************************************************************************/
erase_tagged() { /* erase the tagged files */
int ch;
register int i;
register FILE_ENT *fp;
if (cw.num_tagged == 0) /* are there any tagged files? */
show_error(0,NONE_TAGGED,1,none_tagged);
ch = ask("Erase all tagged files? (y/N): ");
if (!yes(ch))
return;
/* scan files[] looking for tagged files, when found, delete it */
for (i = 0, fp = files; i < cw.nfiles && !brkout(); i++, fp++)
if (fp->flags & TAGGED) {
disp_msg(2,"Erasing ",fp->name);
if (delfile(fp))
delfromwins(fp->dirp,fp->name);
}
clr_msg(); /* clear last erasing msg */
getvolsiz(*cw.dirbuf,&cw.drivep->vol_size, /* volume stats have changed */
&cw.drivep->vol_free,&cw.drivep->clustersiz);
}
/*****************************************************************************
D E L F I L E
*****************************************************************************/
static int
delfile(fp) /* delete a file */
register FILE_ENT *fp;
{
int rc;
char *fn;
fn = fname(fp); /* in case show-all active */
if (fp->flags & DIR) /* special case if file is a DIR */
rc = rmdir(fn); /* try to remove a directory */
else
rc = unlink(fn); /* delete a file */
free(fn);
if (rc) /* delete okay? */
show_error(SHOW_DOS,0,3,"Unable to erase ",fp->name,": ");
return(rc == 0);
}
/******************************************************************************
R E N _ C U R
******************************************************************************/
ren_cur() { /* rename (or move) the current file */
int rc;
register FILE_ENT *fp;
char *newname, fn[MAX_NAMELEN+1];
static char ptxt[] = "Enter new file name or directory name for ";
char *fnp, *target, *todir, *tofn, *dirp, pmsg[sizeof(ptxt)+MAX_NAMELEN+1];
fp = &files[cw.curidx];
strcpy(pmsg,ptxt); /* build prompt string */
strcat(pmsg,strcpy(fn,fp->name));
newname = strupr(prompt("Rename current file",pmsg,NULL,0,MAX_REPLY));
if (strlen(newname) == 0)
return;
/* figure out the full target name, the dir, and the fn */
rc = isadir(dirp=fp->dirp,newname); /* need to know if this is a dir name */
target = parsepath(dirp,fn,newname,rc,&todir,&tofn);
fnp = fname(fp); /* from name */
rc = rename(fnp,target); /* rename/move it */
if (rc == 0) { /* rename okay? */
/* note: fn is a local array instead of a pointer to fp->name because
add2windows() may shift the entries in files[] around thereby making
fp->name point to the wrong file - same goes for local dirp */
add2windows(todir,tofn,fp); /* add to new window(s) */
delfromwins(dirp,fn); /* del from old window(s) */
} else /* unable to rename */
show_error(SHOW_DOS,0,3,"Unable to rename ",fn,": ");
free(target); /* release temp strings */
free(todir);
free(tofn);
free(fnp);
}
/******************************************************************************
R E N _ T A G
******************************************************************************/
ren_tag() { /* rename (move) all tagged files to another dir */
int i, rc;
register FILE_ENT *fp;
char *newdir, *fnp, *target, *todir, *dirp, fn[MAX_NAMELEN+1];
if (cw.num_tagged == 0) /* are there any tagged files? */
show_error(0,NONE_TAGGED,1,none_tagged);
newdir = strupr(prompt("Move tagged files","Enter new directory name",
NULL,0,MAX_REPLY));
if (strlen(newdir) == 0)
return;
/* the name given must be a directory name */
if (!isadir(cw.dirbuf,newdir))
show_error(0,MUST_BE_DIR,1,mustbedir);
/* Okay, move the tagged files */
for (i = 0, fp = files; i < cw.nfiles && !brkout(); i++, fp++)
if (fp->flags & TAGGED) { /* this file tagged? */
/* figure out the target names */
dirp = fp->dirp;
target = parsepath(dirp,strcpy(fn,fp->name),newdir,1,&todir,NULL);
fnp = fname(fp); /* from name */
rc = rename(fnp,target); /* move the file */
if (rc == 0) { /* move okay? */
/* note: fn is a local array instead of a pointer to fp->name 'cause
add2windows() may shift the entries in files[] around thereby making
fp->name point to the wrong file */
add2windows(todir,fn,fp); /* add to new window(s) */
delfromwins(dirp,fn); /* del from old window(s) */
} else /* error, unable to rename/move this file */
show_error(SHOW_DOS,0,3,"Unable to move ",fn,": ");
free(target); /* must be tough on malloc & friends */
free(todir);
free(fnp);
}
}
/******************************************************************************
L O G I N
*****************************************************************************/
login() { /* login to another directory */
char *new_dir, *todir;
new_dir = prompt(NULL,"Login to which drive/directory? ",NULL,0,MAX_REPLY);
/* if they give a relative dir spec and showall is in effect, we want
the relative dir spec to be relative to the current file's dir, not
the current dir */
if (strlen(todir = new_dir)) {
if (cw.showall && cw.curidx < cw.nfiles)
parsepath(files[cw.curidx].dirp,"",new_dir,1,&todir,NULL);
switch_dir(todir);
if (todir != new_dir) /* free mem if parsepath called */
free(todir);
}
}
/******************************************************************************
** S W I T C H _ D I R **
*****************************************************************************/
switch_dir(dir) /* change the current directory */
char *dir;
{
int rc;
register DRIVE_ENT *dp;
if ((rc = change_dir(dir)) == 0) { /* dir switched okay? */
if (cw.showall) /* turn off showall mode if it was */
showoff(); /* in effect in this window */
getcwd(cw.dirbuf,MAX_PATHLEN); /* get the current dir name */
initdrive(*cw.dirbuf); /* (re)init DRIVE_ENT for this drive */
getfiles(); /* load the files[] structure */
adjust_window(); /* resize window data */
update_header(); /* update the header */
update_window(1); /* and the window data */
} else { /* can't switch, tell user */
show_error(SHOW_DOS,0,3,"Can't change to ",dir,": ");
}
return(rc);
}
/*****************************************************************************
I N I T D R I V E
*****************************************************************************/
initdrive(drive) /* initialize DRIVE_ENT for 'drive' */
int drive;
{
register DRIVE_ENT *dp;
dp = findrive(*cw.dirbuf); /* get DRIVE_ENT address 4 drive */
cw.drivep = dp; /* keep address in window block */
get_set_vol(dp->volbuf,NULL); /* get the new volume name */
getvolsiz(*cw.dirbuf,&dp->vol_size, /* and the volume size stats */
&dp->vol_free,&dp->clustersiz);/* incase they are different */
}
/******************************************************************************
F I N D R I V E
*****************************************************************************/
DRIVE_ENT *
findrive(drive) /* find or allocate a DRIVE_ENT for drive */
int drive;
{
register DRIVE_ENT *dp, *ldp = NULL;
dp = drvlst; /* try to find the DRIVE_ENT in the */
while (dp != NULL) { /* linked list of DRIVE_ENTs */
if (dp->drive == drive)
break;
ldp = dp;
dp = dp->next;
}
if (dp == NULL) { /* allocate a new DRIVE_ENT */
dp = (DRIVE_ENT *) Malloc(sizeof(DRIVE_ENT));
dp->next = NULL;
dp->drive = drive;
if (ldp)
ldp->next = dp;
else
drvlst = dp;
}
return(dp);
}
/*****************************************************************************
F I N D I R
*****************************************************************************/
char *
findir(dir) /* find a dirlst entry that matches dir */
char *dir;
{
register int i;
register char **dp;
for (dp = dirlst, i = diridx; i; i--, dp++)
if (strcmp(dir,*dp) == 0)
return(*dp);
return(""); /* better never happen! */
}
/******************************************************************************
** S E T _ V O L **
*****************************************************************************/
set_vol() { /* set the volume label */
char *label;
label = prompt("Set volume label","Enter new volume label: ",NULL,0,11);
if (strlen(label) == 0)
return;
get_set_vol(cw.drivep->volbuf,label); /* one call to set it */
get_set_vol(cw.drivep->volbuf,NULL); /* another to see what comes back */
gotorc(VOL_ROW,1); /* display volume label */
out_str(cw.drivep->volbuf,11,' ');
}
/*****************************************************************************
M A T C H _ N A M E
*****************************************************************************/
match_name(np,pp) /* determine if file name matched pattern */
register char *np, *pp;
{
/* Why you might ask is this code like this, well..., I have plans to port
this code to a system that has file names up to 79 characters long, and
I thought this type of code would be easier to port than something that
knew MS-DOS names are 8+3 */
while (*np) {
if (*np == *pp) /* name char match pattern? */
goto match;
else
if (*np == '.') { /* watch to switches to the */
while (*pp == '*' || *pp == '?') /* extension, the pattern */
pp++; /* must have one also */
if (*pp != '.')
return(0); /* no pattern ext, no match */
goto match;
} else
if (*pp == '*') { /* allow wildcards */
np++; /* NOTE: doesn't advance the */
continue; /* pattern pointer */
} else
if (*pp == '?')
goto match;
else
return(0); /* don't match, not wild */
match:
np++; /* chars match, advance */
pp++;
}
/* the name string matched so far, make sure the pattern only has
wildcards left (if anything) */
while (*pp)
if (*pp != '*' && *pp != '?' && *pp != '.')
return(0);
else
pp++;
return(1); /* A MATCH! */
}
/*****************************************************************************
P A C K F I L E S
*****************************************************************************/
packfiles() { /* pack the files structure */
FILE_ENT *endp;
register FILE_ENT *p, *q;
p = q = files;
endp = &files[cw.nfiles];
while (q < endp)
if (*p->name) {
if (p == q)
p = ++q;
else
p++;
} else
if (*q->name == '\0')
q++;
else {
*p++ = *q;
*q->name = '\0';
q++;
}
cw.nfiles = p - files; /* new # of files in files[] */
}
/*****************************************************************************
F N A M E
*****************************************************************************/
char * ALTCALL
fname(fp) /* return the address of a file name */
register FILE_ENT *fp;
{
return(dirplus(fp,fp->name)); /* maybe this routine is too simple */
}
/*****************************************************************************
D I R P L U S
*****************************************************************************/
char *
dirplus(fp,pp) /* return a string which is the files dir + whatever */
register FILE_ENT *fp;
char *pp;
{
register char *dp;
if (cw.showall) {
dp = (char *) Malloc(strlen(fp->dirp)+strlen(pp)+2);
strcpy(dp,fp->dirp);
if (dp[strlen(dp)-1] != '\\')
strcat(dp,"\\");
strcat(dp,pp);
return(dp);
} else
return(Strdup(pp));
}